package cn.geminis.crypto.cert.service.service;

import cn.geminis.crypto.cert.service.model.*;
import cn.geminis.crypto.core.key.PublicKey;
import cn.geminis.crypto.core.x509.X509Certificate;
import cn.geminis.crypto.csp.AbstractCspFactory;
import org.bouncycastle.asn1.x509.Extension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author puddi
 */
@Service
public class CertServiceImpl implements CertService {

    @Autowired
    private KmcService kmcService;

    @Autowired
    private InstitutionService institutionService;

    @Autowired
    private AbstractCspFactory cspFactory;

    @Override
    public CertSignResponse sign(CertSignRequest request) {
        var result = new CertSignResponse();

        var cert = new X509Certificate();
        cert.setSerialNumber(request.getSerialNumber());
        cert.setSubject(request.getSubject());
        cert.setNotBefore(request.getNotBefore());
        cert.setNotAfter(request.getNotAfter());

        PublicKey publicKey;
        if (Objects.isNull(request.getPublicKey())) {
            var keypairRequest = new KeyPairRequest();
            keypairRequest.setSerialNumber(request.getSerialNumber());
            keypairRequest.setType(request.getKeyType());
            keypairRequest.setNotBefore(request.getNotBefore());
            keypairRequest.setNotAfter(request.getNotAfter());

            if (!StringUtils.isEmpty(request.getProtectPin())) {
                //PIN码不为空，则是P12请求
                keypairRequest.setProtectCert(institutionService.getCert());
            } else {
                keypairRequest.setProtectCert(new X509Certificate(request.getProtectCert()));
            }

            try {
                var keypair = kmcService.requestKeyPair(keypairRequest);
                publicKey = keypair.getPublicKey();
                result.setPrivateKey(keypair.getPrivateKey());
            } catch (Exception e) {
                throw new RuntimeException("从KMC获取密钥错误", e);
            }
        } else {
            publicKey = new PublicKey(request.getPublicKey());
        }

        cert.setPublicKey(publicKey);
        cert.setExtensions(request.getExtensions().stream()
                .map(Extension::getInstance)
                .collect(Collectors.toList()));
        try (var signer = cspFactory.createSigner()) {
            cert.generate(signer, institutionService.getCert());
        } catch (Exception e) {
            throw new RuntimeException("签发证书错误", e);
        }

        if (!StringUtils.isEmpty(request.getProtectPin())) {
            try (var envelope = cspFactory.createEnvelope()) {
                var encryptedKey = result.getPrivateKey();
                var decryptedKey = envelope.decrypt(encryptedKey);
                result.setPrivateKey(decryptedKey);
            } catch (Exception e) {
                throw new RuntimeException("解密私钥错误", e);
            }
        } else {
            result.setCert(cert.getEncode());
        }

        return result;
    }

    @Override
    public CertRevokeResponse revoke(CertRevokeRequest request) {
        return null;
    }

    @Override
    public CertDelayResponse delay(CertDelayRequest request) {
        return null;
    }

    @Override
    public CertResumeResponse resume(CertResumeRequest request) {
        return null;
    }
}
